home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 331_01 / roff.c < prev    next >
Text File  |  1990-05-30  |  16KB  |  657 lines

  1. /*
  2. HEADER
  3.  */
  4. /* Reform paragraphs.  Dot commands in the text are interpreted and
  5.  * left in the result.  Adapted from CUG .. 3/15/87 G. Osborn.
  6.  *
  7.  * All automatic pagination output is suppressed until a .he command
  8.  * is processed.  The text portion of the .he command may be null.
  9.  *
  10.  * dot commands to not contribute to the line count if left
  11.  * in the output.
  12.  */
  13.  
  14. #include <ctype.h>
  15. #include <stdio.h>
  16. #include "ged.h"
  17.  
  18.  
  19.  
  20. #define PAGEWIDTH 72    /* default page width */
  21. #define PAGELINES  66   /* default page length */
  22. #define PAGECHAR '#'    /* page number escape char */
  23.  
  24. static int fill;                 /* in fill mode if YES */
  25. static int lsval;                /* current line spacing */
  26. static int inval;                /* current indent; >= 0 */
  27. static int rmval;                /* current right margin */
  28. static int ceval;                /* number of lines to center */
  29. static int ulval;                /* number of lines to underline */
  30. static int curpag;               /* current output page number */
  31. static int newpag;               /* next output page number */
  32. static int pageline;             /* next line to be printed */
  33. static int plval;                /* page length in lines */
  34. static int m1val;                /* top margin, including header */
  35. static int m2val;                /* margin after header */
  36. static int m3val;                /* margin after last text line */
  37. static int m4val;                /* bottom margin, including footer */
  38. static int bottom;               /* last live line on page: */
  39. static int dir;                  /* directions flag */
  40. static char *header;             /* top of page title */
  41. static char *footer;             /* bottom of page title */
  42. static char *outbuf;             /* lines to be filled go here */
  43. static int inline, outline;
  44. static int outp;
  45. static int para1;                 /* excess paragraph indentation of 1st line of paragraph */
  46. static int paraphase;
  47.  
  48. /* ----------------------------- */
  49. /* keep dot commands if keep not 0.
  50.  */
  51. roff(keep)
  52. int keep;
  53. {
  54.     register i;
  55.     char inbuf[LLIM];
  56.     int c, ncline, msgline, lastlsav;
  57.     char *sp;
  58.     char *getline();
  59.     char temp[81];
  60.     char buf1[LLIM];
  61.     char buf2[LLIM];
  62.     char buf3[LLIM];
  63.  
  64.  
  65. /* the large buffers are automatic so that they do not occupy permanent
  66.  * storage.  The pointers to them are global within this file.
  67.  */
  68.     header = &buf1[0];
  69.     footer = &buf2[0];
  70.     outbuf = &buf3[0];
  71.  
  72. /* don't retain memory of state after previous call */
  73.     fill = YES;
  74.     lsval = 1;
  75.     inval = 0;
  76.     rmval = PAGEWIDTH;
  77.     ceval = 0;
  78.     ulval = 0;
  79.     curpag = 0;
  80.     newpag = 1;
  81.     pageline = 0;
  82.     plval = PAGELINES;
  83.     m1val = 2;
  84.     m2val = 3;
  85.     m3val = 2;
  86.     m4val = 3;
  87.     bottom = plval - m3val - m4val; /* invariant */
  88.     header[0] = '\0';
  89.     footer[0] = '\0';
  90.  
  91.  
  92. /* Old lines are deleted in blocks of 100 because deltp is slow for large
  93.  * documents.  Its execution time is independent of the number of
  94.  * lines deleted.
  95.  */
  96.     inline = 1;
  97.     lastlsav = lastl;
  98.     msgline = 0;
  99.     outline = lastl;
  100.     outbuf[0] = '\0';
  101.     outp = 0;
  102.     paraphase = 0;    /* expecting first line of paragraph */
  103.  
  104.     while (inline <= lastlsav) {
  105.         strcpy(inbuf,getline(inline));
  106.         if ( (inline + msgline ) == 1 || (inline % 100) == 0) {
  107.             sprintf(temp,"Reforming per dot commands.  Line %d", inline+msgline);
  108.             putmess(temp);
  109.         }
  110.         if ((inline % 100) == 0) {
  111.             deltp(1,100);
  112.             inline -= 100;
  113.             lastlsav -= 100;
  114.             outline -= 100;
  115.             msgline += 100;
  116.         }
  117.         if (inline + msgline == cline)
  118.             ncline = outline - lastlsav;
  119.         inline++;
  120.  
  121. /* it is necessary to flush the output buffer before dot commands
  122.  * if they are left in the output.
  123.  */
  124.         if (inbuf[0] == '.' && isalpha(inbuf[1]) ) {
  125.             if (keep) {
  126.                 putwrd("");   /* flush the output buffer */
  127.                 inject(outline++,inbuf);  /* leave the dot commands in for further editing */
  128.             }
  129.             command(inbuf);
  130.         }
  131.         else {
  132.             proctext(inbuf);
  133.         }
  134.     }
  135.     putwrd("");   /* round it out */
  136.     space(10000);
  137.  
  138.     if (lastlsav > 0)
  139.         deltp(1,lastlsav);  /* delete the last of the old */
  140.  
  141.     plast = -1;
  142.     moveline (ncline-cline);  /* go back to the original point, which is not now at the same line number */
  143.     blankedmess = YES;
  144.     return;
  145. }
  146.  
  147.  
  148.  
  149.  
  150.  
  151. /* perform formatting command */
  152.  
  153. command(buf)
  154. char *buf;
  155. {
  156.     int val, spval;
  157.     char *argtyp;
  158.  
  159.     val = getval(buf,argtyp);  /* get numerical argument and type */
  160. /* begin page */
  161.     if (lookup(buf, "bp")) {
  162.         if (pageline > 0)
  163.             space(10000);   /* maxint overflows */
  164.         set(&curpag, val, argtyp, curpag+1, -MAXINT, MAXINT);
  165.         newpag = curpag;
  166.     }
  167. /* break */
  168.     else if (lookup(buf,"br"))
  169.         putwrd("");
  170. /* center */
  171.     else if (lookup(buf,"ce")) {
  172.         putwrd("");
  173.         set(&ceval,val,argtyp,1,0,MAXINT);
  174.     }
  175. /* fill */
  176.     else if (lookup(buf,"fi")) {
  177.         putwrd("");
  178.         fill = YES;
  179.     }
  180. /* footnote */
  181.     else if (lookup(buf,"fo")) {
  182.         putwrd("");
  183.         strcpy(footer,buf+3);
  184.     }
  185. /* header */
  186.     else if (lookup(buf,"he")) {
  187.         putwrd("");
  188.         strcpy(header,buf+3);
  189.         if (header[0] == '\0')
  190.             strcpy(header," ");   /* activate pagination */
  191.     }
  192. /* indent */
  193.     else if (lookup(buf,"in")) {
  194.         set(&inval, val, argtyp, 0, 0, rmval-1);
  195.     }
  196.     else if (lookup(buf,"ls"))
  197.         set(&lsval,val,argtyp,1,1,MAXINT);
  198.  
  199. /* need at least n lines before new page */
  200.     else if (lookup(buf, "ne")) {
  201.         if (val + pageline - 1  > bottom)
  202.             space(10000);
  203.     }
  204.     else if (lookup(buf,"nf")) {
  205.         putwrd("");  /* runout */
  206.         fill = NO;
  207.     }
  208.     else if (lookup(buf,"pl")) {
  209.         set(&plval, val, argtyp, PAGELINES, m1val+m2val+m3val+m4val+1, MAXINT);
  210.         bottom=plval-m3val-m4val;
  211.     }
  212.     else if (lookup(buf,"rm")) {
  213.         putwrd("");
  214.         set(&rmval, val, argtyp, PAGEWIDTH, inval+1, MAXINT);
  215.     }
  216.     else if (lookup(buf,"sp")) {
  217.         set(&spval,val,argtyp,1,0,MAXINT);
  218.         putwrd("");
  219.         space(spval);
  220.     }
  221.     else if (lookup(buf,"ul"))
  222.         set(&ulval,val,argtyp,0,1,MAXINT);
  223.     else
  224.         return;    /* ignore unknown commands */
  225. }
  226.  
  227.  
  228. /* lookup routine for commands */
  229.  
  230. lookup(buf,string)
  231. char *buf, *string;
  232. {
  233.     return (buf[1] == string[0]) && (buf[2] == string[1]);
  234. }
  235.  
  236.  
  237. /* evaluate optional numeric argument */
  238.  
  239. getval(buf,argtyp)
  240. char *buf, *argtyp;
  241. {
  242.     int i;
  243.  
  244.     i = 3;
  245. /* ..find argument.. */
  246.     while (buf[i] == ' ' || buf[i] == '\t')
  247.         ++i;
  248.     *argtyp = buf[i];
  249.     if (*argtyp == '+' || *argtyp=='-')
  250.         i++;
  251.  
  252.     return(atoi(buf+i));
  253. }
  254.  
  255.  
  256. /* set parameter and check range */
  257.  
  258. set(param,val,argtyp,defval,minval,maxval)
  259. int *param,val,defval,minval,maxval;
  260. char *argtyp;
  261. {
  262.     if (*argtyp == '\0')
  263.         *param = defval;
  264.     else if (*argtyp == '+')
  265.         *param += val;
  266.     else if (*argtyp == '-')
  267.         *param -= val;
  268.     else
  269.         *param = val;
  270.  
  271.     *param = min(*param,maxval);
  272.     *param = max(*param,minval);
  273. }
  274.  
  275. /* ------------- reformat text lines ------------------- */
  276.  
  277. proctext(inbuf)
  278. char *inbuf;
  279. {
  280.     char wrdbuf[LLIM];
  281.     char *nl;
  282.     int save, inpoint;
  283.     int i, j;
  284.  
  285.  
  286.     for (inpoint = 0; inbuf[inpoint] == ' '; inpoint++)
  287.         ;
  288.     if (fill) {
  289.  
  290. /* determine additional indentation for first line of paragraph, if any */
  291.         if (inbuf[0] == '\0') {
  292.             paraphase = 0;    /* looking for 1st line of paaragraph */
  293.         }
  294.         else if (paraphase == 0) {
  295.             paraphase = 1;
  296.             if (inline <= lastl) {   /* use preceeding value if last line */
  297.                 nl = getline(inline);   /* next line */
  298.                 for (j = 0; nl[j] == ' '; j++)
  299.                     ;
  300.                 pa